using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using Edge.Common.DataUtils;
using Edge.Common.DataUtils;

namespace Edge.Common.Web
{
    [Serializable]
    public class UrlBuilder : UriBuilder, ICloneable
    {
        HashtableBehaviorlDictionary<string, string> _queryString = new HashtableBehaviorlDictionary<string, string>(StringComparer.OrdinalIgnoreCase);

        #region Properties
        public IDictionary<string, string> QueryString
        {
            get
            {
                return _queryString;
            }
        }

        public string PageName
        {
            get
            {
                string path = base.Path;
                return path.Substring(path.LastIndexOf("/") + 1);
            }
            set
            {
                string path = base.Path;
                path = path.Substring(0, path.LastIndexOf("/"));
                base.Path = string.Concat(path, "/", value);
            }
        }
        #endregion

        #region Constructor overloads
        public UrlBuilder()
            : base()
        {
        }

        public static UrlBuilder FromPage(string pageUrl)
        {
            HttpContext ctx = HttpContext.Current;
            if (ctx == null)
                throw new InvalidOperationException();
            string appPath = ctx.Request.ApplicationPath;
            if (!appPath.EndsWith("/"))
                appPath += "/";
            string url = "http://" + ctx.Request.Url.Authority + appPath + pageUrl;
            return new UrlBuilder(url);
        }

        public static UrlBuilder FromCurrentRequest()
        {
            HttpContext ctx = HttpContext.Current;
            if (ctx == null)
                throw new InvalidOperationException();
            string url = ctx.Request.Url.ToString();
            return new UrlBuilder(url);
        }

        public UrlBuilder(string uri)
            : base(uri)
        {
            PopulateQueryString();
        }


        public UrlBuilder(Uri uri)
            : base(uri)
        {
            PopulateQueryString();
        }

        public UrlBuilder(Uri uri, string extraValue)
            : base(uri)
        {
            Query = extraValue;
            PopulateQueryString();
        }

        public UrlBuilder(string schemeName, string hostName)
            : base(schemeName, hostName)
        {
            PopulateQueryString();
        }

        public UrlBuilder(string scheme, string host, int portNumber)
            : base(scheme, host, portNumber)
        {
            PopulateQueryString();
        }

        public UrlBuilder(string scheme, string host, int port, string pathValue)
            : base(scheme, host, port, pathValue)
        {
            PopulateQueryString();
        }

        public UrlBuilder(string scheme, string host, int port, string path, string extraValue)
            : base(scheme, host, port, path, extraValue)
        {
            PopulateQueryString();
        }


        public UrlBuilder(System.Web.UI.Page page)
            : base(page.Request.Url.AbsoluteUri)
        {
            PopulateQueryString();
        }
        #endregion

        #region Public methods
        public new string ToString()
        {
            MakeQueryString();

            return base.Uri.AbsoluteUri;
        }

        public UrlBuilder SetParams(string key, string value)
        {
            this.QueryString[key] = value;
            return this;
        }

        public void Navigate()
        {
            _Navigate(true);
        }

        public void Navigate(bool endResponse)
        {
            _Navigate(endResponse);
        }

        private void _Navigate(bool endResponse)
        {
            string uri = this.ToString();
            HttpContext.Current.Response.Redirect(uri, endResponse);
        }
        #endregion

        #region Private methods
        private void PopulateQueryString()
        {
            string query = base.Query;

            if (query == string.Empty || query == null)
            {
                return;
            }

            _queryString.Clear();

            query = query.Substring(1); //remove the ?

            string[] pairs = query.Split(new char[] { '&' });
            foreach (string s in pairs)
            {
                string[] pair = s.Split(new char[] { '=' });

                _queryString[pair[0]] = (pair.Length > 1) ? pair[1] : string.Empty;
            }
        }



        private void MakeQueryString()
        {
            int count = QueryString.Count;

            if (count == 0)
            {
                base.Query = string.Empty;
                return;
            }

            string[] keys = new string[count];
            string[] values = new string[count];
            string[] pairs = new string[count];

            QueryString.Keys.CopyTo(keys, 0);
            QueryString.Values.CopyTo(values, 0);

            for (int i = 0; i < count; i++)
            {
                pairs[i] = string.Concat(keys[i], "=", values[i]);
            }

            base.Query = string.Join("&", pairs);
        }
        #endregion

        public object Clone()
        {
            return new UrlBuilder(this.Uri);
        }
    }
}